/* eslint-disable @typescript-eslint/no-explicit-any */
import axios, { AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import { API } from './types'
import {
  decryptData,
  generateNonce,
  generateSignature,
  sortObjectKeys,
} from '@/utils/encryption'
import { upperCase } from 'lodash'

const isProduction = import.meta.env.PROD
const productionBaseUrl = import.meta.env.VITE_BASE_URL

const httpInstance = axios.create({
  baseURL: isProduction ? productionBaseUrl : '',
  timeout: 10000,
})

httpInstance.interceptors.request.use(handleRequest)
httpInstance.interceptors.response.use(handleResponse)

async function handleRequest(
  config: InternalAxiosRequestConfig,
): Promise<InternalAxiosRequestConfig> {
  if (import.meta.env.DEV) {
    return config
  }
  const uri = config.url?.split('?')[0] || ''
  const body =
    upperCase(config.method) === 'GET'
      ? '{}'
      : JSON.stringify(sortObjectKeys(config.data))
  const signature = await generateSignature(
    upperCase(config.method),
    uri,
    String(new Date().getTime()),
    generateNonce(),
    body,
  )
  return {
    ...config,
    headers: {
      ...config.headers,
      Authorization: `SHA256-RSA2048 ${signature}`,
    } as any,
  }
}

async function handleResponse<S>(
  response: AxiosResponse<API.Response<S>>,
): Promise<AxiosResponse<API.Response<S>>> {
  if (import.meta.env.DEV) {
    return response
  }
  const { status, statusText, data } = response
  const { errcode, errmsg, result } = data
  const decryptedResult = JSON.parse(decryptData(result as string)) as S
  return {
    ...response,
    status,
    statusText,
    data: {
      errcode,
      errmsg,
      result: decryptedResult,
    },
  }
}

export function login(req: API.LoginReq) {
  return httpInstance.post<API.LoginRes>('/api/base/v3/admin/login/face', req)
}

export function getToken(req: API.GetTokenReq) {
  return httpInstance.post<API.GetTokenRes>('/api/base/v1/admin/login', req)
}

export function resetPassword(req: API.ResetPasswordReq) {
  return httpInstance.post<API.ResetPasswordRes>(
    '/api/sched/v1/expert/password/reset',
    req,
  )
}
